const fs = require("fs-extra");
const path = require("path");
const archiver = require("archiver");
const chalk = require("chalk");

class FileUtils {
  static async createOutputDir(folderName) {
    const outputDir = path.join(process.cwd(), "output", folderName);

    // 确保目录存在
    await fs.ensureDir(outputDir);

    // 清空目录（如果存在旧文件）
    await fs.emptyDir(outputDir);

    return outputDir;
  }

  static async compressFolder(sourceDir, outputName) {
    const outputPath = path.join(process.cwd(), "output");
    const zipPath = path.join(outputPath, `${outputName}.zip`);

    // 确保输出目录存在
    await fs.ensureDir(outputPath);

    return new Promise((resolve, reject) => {
      // 创建写入流
      const output = fs.createWriteStream(zipPath);
      const archive = archiver("zip", {
        zlib: { level: 9 }, // 最高压缩级别
      });

      output.on("close", () => {
        console.log(
          chalk.green(`✨ 压缩完成: ${zipPath} (${archive.pointer()} bytes)`)
        );
        resolve(zipPath);
      });

      output.on("error", (err) => {
        reject(err);
      });

      archive.on("error", (err) => {
        reject(err);
      });

      // 连接流
      archive.pipe(output);

      // 添加文件夹到压缩包
      archive.directory(sourceDir, path.basename(sourceDir));

      // 完成压缩
      archive.finalize();
    });
  }

  static async compressFiles(files, outputName) {
    const outputPath = path.join(process.cwd(), "output");
    const zipPath = path.join(outputPath, `${outputName}.zip`);

    // 确保输出目录存在
    await fs.ensureDir(outputPath);

    return new Promise((resolve, reject) => {
      const output = fs.createWriteStream(zipPath);
      const archive = archiver("zip", {
        zlib: { level: 9 },
      });

      output.on("close", () => {
        console.log(
          chalk.green(`✨ 压缩完成: ${zipPath} (${archive.pointer()} bytes)`)
        );
        resolve(zipPath);
      });

      output.on("error", reject);
      archive.on("error", reject);

      archive.pipe(output);

      // 添加文件
      for (const [fileName, filePath] of Object.entries(files)) {
        archive.file(filePath, { name: fileName });
      }

      archive.finalize();
    });
  }

  static async writeFile(filePath, content) {
    // 确保目录存在
    await fs.ensureDir(path.dirname(filePath));

    // 写入文件
    await fs.writeFile(filePath, content, "utf8");

    return filePath;
  }

  static async readFile(filePath) {
    try {
      return await fs.readFile(filePath, "utf8");
    } catch (error) {
      throw new Error(`读取文件失败: ${filePath} - ${error.message}`);
    }
  }

  static async fileExists(filePath) {
    try {
      await fs.access(filePath);
      return true;
    } catch {
      return false;
    }
  }

  static async deleteFile(filePath) {
    try {
      await fs.remove(filePath);
      return true;
    } catch (error) {
      console.warn(
        chalk.yellow(`⚠️  删除文件失败: ${filePath} - ${error.message}`)
      );
      return false;
    }
  }

  static async copyFile(source, destination) {
    await fs.ensureDir(path.dirname(destination));
    await fs.copy(source, destination);
    return destination;
  }

  static formatFileSize(bytes) {
    const units = ["B", "KB", "MB", "GB"];
    let size = bytes;
    let unitIndex = 0;

    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }

    return `${size.toFixed(1)} ${units[unitIndex]}`;
  }

  static async getFileStats(filePath) {
    try {
      const stats = await fs.stat(filePath);
      return {
        size: stats.size,
        created: stats.birthtime,
        modified: stats.mtime,
        isFile: stats.isFile(),
        isDirectory: stats.isDirectory(),
      };
    } catch (error) {
      throw new Error(`获取文件信息失败: ${filePath} - ${error.message}`);
    }
  }

  static async listFiles(dirPath, extensions = []) {
    try {
      const files = await fs.readdir(dirPath);
      const result = [];

      for (const file of files) {
        const filePath = path.join(dirPath, file);
        const stats = await fs.stat(filePath);

        if (stats.isFile()) {
          if (
            extensions.length === 0 ||
            extensions.includes(path.extname(file))
          ) {
            result.push({
              name: file,
              path: filePath,
              size: stats.size,
              modified: stats.mtime,
            });
          }
        }
      }

      return result;
    } catch (error) {
      throw new Error(`列出文件失败: ${dirPath} - ${error.message}`);
    }
  }
}

module.exports = {
  createOutputDir: FileUtils.createOutputDir.bind(FileUtils),
  compressFolder: FileUtils.compressFolder.bind(FileUtils),
  compressFiles: FileUtils.compressFiles.bind(FileUtils),
  writeFile: FileUtils.writeFile.bind(FileUtils),
  readFile: FileUtils.readFile.bind(FileUtils),
  fileExists: FileUtils.fileExists.bind(FileUtils),
  deleteFile: FileUtils.deleteFile.bind(FileUtils),
  copyFile: FileUtils.copyFile.bind(FileUtils),
  formatFileSize: FileUtils.formatFileSize.bind(FileUtils),
  getFileStats: FileUtils.getFileStats.bind(FileUtils),
  listFiles: FileUtils.listFiles.bind(FileUtils),
};
